package com.apes.fn.scm.internal.help.service.voucher.sale;

import com.apes.fn.scm.internal.help.model.InternalHelpReturnApproval;
import com.apes.fn.scm.internal.help.model.InternalHelpReturnApprovalItem;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.fn.server.workOrder.repository.MaintenanceOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleOrder.SaleOrderItem;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 经销带安退货
 * 服务工单外协部分，经销带安
 *
 * @Author wuq
 * @Date 2021-10-19
 */
@Service
public class SalePlanOutHelpReturnVoucherService extends DomainService {

    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private ServicePlanItemRepository servicePlanItemRepository;
    @Autowired
    private MaintenanceOrderRepository maintenanceOrderRepository;

    public void process(Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        List<SaleOrderItem> saleOrderItems = new ArrayList<>(param.keySet());
        SaleOrder saleOrder = saleOrderItems.get(0).getSaleOrder();

        saleOrderItems.stream().collect(Collectors.groupingBy(saleOrderItem -> getMaintenanceOrderContract(saleOrderItem.getOriginItemId())))
                .forEach((contract, orderItems) -> {

                    // 判断合同公司与工单上面的公司是否一致
                    if ("supplier".equals(contract.getContractType().getCode()) && !Objects.equals(contract.getCompany().getId(), saleOrder.getCompany().getId())) {
                        // 退跨公司采购
                        returnCrossPurchaseVoucher(contract, saleOrder, saleOrderItems, param);
                    } else {
                        // 直接退供应商采购
                        returnOutPurchaseVoucher(contract, contract.getPartner(), saleOrder, saleOrderItems, param);
                    }
                });
    }

    private Contract getMaintenanceOrderContract(String id) {
        ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(id);
        Optional.ofNullable(servicePlanItem).orElseThrow(() -> new RuntimeException(String.format("根据零售明细单来源行号[%s]获取服务方案明细行失败！", id)));

        MaintenanceOrder maintenanceOrder = maintenanceOrderRepository.findFirstByServicePlanItemAndBusinessTypeNotIn(servicePlanItem, Collections.singletonList("out"));
        return maintenanceOrder.getContract();
    }

    private void returnCrossPurchaseVoucher(Contract contract, SaleOrder saleOrder, List<SaleOrderItem> saleOrderItems,
                                            Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        PartyRole company = contract.getCompany().getParty().getPartyRoleByType("Company");         // 合同上面的公司
        PartyRole partner = saleOrder.getCompany().getParty().getPartyRoleByType("Customer");       // 门店公司

        // 第一步：内协门店做返厂
        Contract innerContract = contractService.getContract(saleOrder.getDept(), company.getParty().getPatyRoleByType("Supplier"), "distribution", "supplier", "分销单经销带安退回");
        returnOutPurchaseVoucher(innerContract, company, saleOrder, saleOrderItems, param);

        // 第二步：退合同公司对门店的销售
        // 找原内部销售凭证
        String originNumber = saleOrderItems.get(0).getOriginItemId();                // 门店方案明细行号
        Voucher originSaleVoucher = voucherRepository.findSaleVoucherByCompanyAndItemOrigin(company, partner, originNumber);
        returnSaleVoucher(saleOrderItems, originSaleVoucher, param);

        // 第三步：退合同公司对供应商的采购
        returnSupplierPurchaseVoucher(contract, originSaleVoucher, saleOrderItems, param);
    }

    private void returnOutPurchaseVoucher(Contract contract, PartyRole partner, SaleOrder saleOrder, List<SaleOrderItem> saleOrderItems,
                                          Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        List<InternalHelpReturnApprovalItem> returnApprovalItems = saleOrderItems.stream().map(param::get).collect(Collectors.toList());
        InternalHelpReturnApproval internalHelpReturnApproval = returnApprovalItems.get(0).getApproval();

        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.PURCHASE_RETURN);

        voucher.setContract(contract);
        voucher.setPartner(partner.getParty().getPartyRoleByType("Supplier"));
        voucher.setCompany(saleOrder.getCompany());
        voucher.setDept(saleOrder.getDept());
        voucher.setClerk(internalHelpReturnApproval.getApplyUid());

        voucher.setInventoryMode(contract.getCooperation().getInventoryMode());
        voucher.setAccountingMethod(contract.getCooperation().getAccountingMethod());

        voucher.setScene(internalHelpReturnApproval.getScene());
        voucher.setOrigin(internalHelpReturnApproval.getOrigin());
        voucher.setOriginBusinessType(internalHelpReturnApproval.getOriginBusinessType());
        voucher.setSource(internalHelpReturnApproval.getId());
        voucher.setSourceBusinessType(internalHelpReturnApproval.getInnerBusinessType());
        voucher.setCustomerExpand(internalHelpReturnApproval.getCustomerExpand().getId());

        voucher.setVoucherItems(
                returnApprovalItems.stream()
                        .map(item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());

                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(-1.00 * item.getProductReturnQty());
                            voucherItem.setOriginItemId(String.valueOf(item.getId()));
                            voucherItem.setSourceItemId(String.valueOf(item.getId()));
                            voucherItem.setOwner(saleOrder.getCompany());

                            SaleOrderItem saleOrderItem = saleOrderItems.stream().filter(saleItem -> Objects.equals(saleItem.getId(), item.getOriginItemId())).findFirst().get();

                            // 获取原采购批次
                            InventoryBatch inventoryBatch = saleOrderItem.getInventoryBatch();
                            voucherItem.setInventoryBatch(inventoryBatch);
                            voucherItem.setPriceUnit(inventoryBatch.getTaxCostPrice());
                            voucherItem.setSupplier(inventoryBatch.getSupplier());
                            voucherItem.setTax(inventoryBatch.getTax());

                            //  增加（减少）冻结数量
                            inventoryService.changeFrostQty(inventoryBatch, item.getUom(), item.getProductReturnQty(), inventoryBatch.getCompany(),
                                    internalHelpReturnApproval.getInnerBusinessType(), internalHelpReturnApproval.getId(), item.getId(), "生成零售外协商品返厂凭证");

                            return voucherItem;
                        }).collect(Collectors.toSet()));

        Voucher newVoucher = invoke("voucher.create", MapUtil.mapped(voucher));
        if ("IM_OWN".equals(newVoucher.getInventoryMode())) {
            invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(newVoucher))));
        }
    }


    private void returnSaleVoucher(List<SaleOrderItem> saleOrderItems, Voucher originSaleVoucher,
                                   Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        List<InternalHelpReturnApprovalItem> returnApprovalItems = saleOrderItems.stream().map(param::get).collect(Collectors.toList());
        InternalHelpReturnApproval internalHelpReturnApproval = returnApprovalItems.get(0).getApproval();

        Voucher voucher = new Voucher();
        // 销售退回必填字段
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.SALE_RETURN);
        voucher.setVoucher(originSaleVoucher);

        ReflectUtil.copy(originSaleVoucher, voucher, "dept", "company", "partner", "contract");
        voucher.setInventoryMode(originSaleVoucher.getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(originSaleVoucher.getAccountingMethod());  // 核算方式

        voucher.setCustomerExpand(internalHelpReturnApproval.getCustomerExpand().getId());
        voucher.setScene(internalHelpReturnApproval.getScene());
        voucher.setOrigin(internalHelpReturnApproval.getOrigin());
        voucher.setOriginBusinessType(internalHelpReturnApproval.getOriginBusinessType());
        voucher.setSource(internalHelpReturnApproval.getId());
        voucher.setSourceBusinessType(internalHelpReturnApproval.getInnerBusinessType());

        voucher.setVoucherItems(
                originSaleVoucher.getVoucherItems().stream().map(saleItem -> {
                    VoucherItem voucherItem = new VoucherItem();

                    returnApprovalItems.stream()
                            .filter(returnItem -> returnItem.getProduct().getId().equals(saleItem.getProduct().getId()))
                            .forEach(retailReturnItem -> {

                                voucherItem.setProduct(saleItem.getProduct());
                                voucherItem.setTax(saleItem.getTax());

                                voucherItem.setUom(saleItem.getUom());          // 设置为销售的单位以及数量
                                voucherItem.setProductQty(-1 * Math.abs(saleItem.getProductQty()));
                                voucherItem.setPriceUnit(saleItem.getPriceUnit());      // 默认为退货单价
                                voucherItem.setOwner(originSaleVoucher.getCompany());

                                voucherItem.setOriginItemId(retailReturnItem.getId());
                                voucherItem.setSourceItemId(retailReturnItem.getId());
                                voucherItem.setVoucherItem(saleItem);   // 退回时传入明细行号
                            });

                    return voucherItem;
                }).filter(voucherItem -> voucherItem.getProduct() != null).collect(Collectors.toSet()));

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        if ("IM_OWN".equals(voucher.getInventoryMode())) {
            invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
        }

    }

    private void returnSupplierPurchaseVoucher(Contract contract, Voucher originSaleVoucher, List<SaleOrderItem> saleOrderItemList,
                                               Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        List<InternalHelpReturnApprovalItem> returnApprovalItems = saleOrderItemList.stream().map(param::get).collect(Collectors.toList());
        InternalHelpReturnApproval internalHelpReturnApproval = returnApprovalItems.get(0).getApproval();

        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.PURCHASE_RETURN);

        voucher.setContract(contract);
        voucher.setPartner(contract.getPartner().getParty().getPartyRoleByType("Supplier"));
        voucher.setCompany(contract.getCompany());
        voucher.setDept(contract.getDept());
        voucher.setClerk(internalHelpReturnApproval.getApplyUid());

        voucher.setInventoryMode(contract.getCooperation().getInventoryMode());
        voucher.setAccountingMethod(contract.getCooperation().getAccountingMethod());

        voucher.setScene(internalHelpReturnApproval.getScene());
        voucher.setOrigin(internalHelpReturnApproval.getOrigin());
        voucher.setOriginBusinessType(internalHelpReturnApproval.getOriginBusinessType());
        voucher.setSource(internalHelpReturnApproval.getId());
        voucher.setSourceBusinessType(internalHelpReturnApproval.getInnerBusinessType());
        voucher.setCustomerExpand(internalHelpReturnApproval.getCustomerExpand().getId());

        voucher.setVoucherItems(
                returnApprovalItems.stream()
                        .filter(item -> LogicalUtil.in(item.getProduct().getType(), "aut"))
                        .map(item -> {
                            VoucherItem voucherItem = new VoucherItem();

                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(-1.00 * item.getProductReturnQty());
                            voucherItem.setOriginItemId(String.valueOf(item.getId()));
                            voucherItem.setSourceItemId(String.valueOf(item.getId()));
                            voucherItem.setOwner(contract.getCompany());

                            //找到原销售凭证的明细行
                            VoucherItem saleVoucherItem = originSaleVoucher.getVoucherItems().stream()
                                    .filter(saleItem -> saleItem.getProduct().getId().equals(item.getProduct().getId()))
                                    .findFirst()
                                    .orElseThrow(() -> new RuntimeException("生成返厂凭证时，根据商品编码没有找到对应的凭证明细，" +
                                            "商品编码：" + item.getProduct().getId() + "，凭证编码：" + originSaleVoucher.getId()));

                            // 获取原销售批次
                            VoucherInventory voucherInventory = voucherInventoryRepository.findAll(
                                    JpaDsl.toCriteriaByEq("voucher.id", originSaleVoucher.getId(), "voucherItem", saleVoucherItem))
                                    .stream().findFirst().get();

                            InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();
                            voucherItem.setInventoryBatch(inventoryBatch);
                            voucherItem.setPriceUnit(inventoryBatch.getTaxCostPrice());
                            voucherItem.setSupplier(inventoryBatch.getSupplier());
                            voucherItem.setTax(inventoryBatch.getTax());

                            //  增加（减少）冻结数量
                            inventoryService.changeFrostQty(inventoryBatch, item.getUom(), item.getProductReturnQty(), inventoryBatch.getCompany(),
                                    internalHelpReturnApproval.getInnerBusinessType(), internalHelpReturnApproval.getId(), item.getId(), "生成零售服务商品返厂凭证");

                            return voucherItem;
                        }).collect(Collectors.toSet()));

        Voucher newVoucher = invoke("voucher.create", MapUtil.mapped(voucher));
        if ("IM_OWN".equals(newVoucher.getInventoryMode())) {
            invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(newVoucher))));
        }
    }
}
